/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package tarea1automatas;

import java.util.*;
import java.io.*;

/**
 *
 * @author MarioEspinoza
 */
public class AutomataFinito {
    
    protected ArrayList<Estado> estados;
    protected ArrayList<String> simbolosLenguaje;
    private boolean esDeterminista;
    
    public AutomataFinito()
    {
        estados = new ArrayList<Estado>();
        simbolosLenguaje = new ArrayList<String>();
    }

    public void leerAutomataFinito(ArrayList<String> lineas)
    {
        int cantidadEstados=0;
        int cantidadSimbolos;
        try
        {
            int cantidadLineas = lineas.size();
            if(cantidadLineas<4)
            {
                System.out.println("Formato archivo invalido");
                return;
            }
            for (int i = 0; i < cantidadLineas; i++)
            {
                if (i == 0)
                {
                    cantidadEstados = Integer.parseInt(lineas.get(i));
                    estados = new ArrayList<Estado>(cantidadEstados);

                    
                }
                if(i==1)
                {
                    String[] simbolosLeidos = lineas.get(i).split(" ");
                    cantidadSimbolos = simbolosLeidos.length;

                    for (int j = 0; j < cantidadSimbolos; j++)
                    {
                        simbolosLenguaje.add(simbolosLeidos[j]);
                    }

                    for(int j=0;j<cantidadEstados;j++)
                    {
                        Estado estado = new Estado(j,cantidadEstados,cantidadSimbolos);
                        estados.add(estado);
                    }
                }
                if (i == 2)
                {

                    Estado inicial = estados.get(Integer.parseInt(lineas.get(i)));
                    inicial.setEstadoInicial(true);

                    estados.set(inicial.getNombre(), inicial);
                }
                if (i == 3)
                {
                    String[] finales = lineas.get(i).split(" ");

                    for (int j = 0; j < finales.length; j++)
                    {
                        int index = Integer.parseInt(finales[j]);
                        Estado temporal = estados.get(index);
                        temporal.setEstadoFinal(true);
                        this.estados.set(index, temporal);
                    }
                }
                if(i>3)
                {
                    String[] elementosTransicion = lineas.get(i).split(" ");
                    Estado temporal = null;
                    String palabraTransicion = null;
                    int indexEstado = -1;

                    for (int j = 0; j < elementosTransicion.length; j++)
                    {
                        if(j==0)
                        {
                            indexEstado = Integer.parseInt(elementosTransicion[j]);
                            temporal = estados.get(indexEstado);
                        }
                        if(j==1)
                        {

                            if(temporal!=null)
                            {
                                palabraTransicion = elementosTransicion[j];
                                if(simbolosLenguaje.contains(palabraTransicion))
                                {
                                    if(palabraTransicion.equals("e"))
                                        esDeterminista=esDeterminista&&false;
                                    else
                                        esDeterminista=esDeterminista&&true;
                                    if(palabraTransicion.contains("e") && !palabraTransicion.equals("e"))
                                        palabraTransicion = palabraTransicion.replace("e", "");

                                }
                                else
                                    esDeterminista=esDeterminista&&false;
                            }
                        }
                        if(j>1)
                        {
                            if(temporal!=null && palabraTransicion!=null)
                            {
                                int estadoDestino = Integer.parseInt(elementosTransicion[j]);
                                Integer indicePalabra = Integer.MAX_VALUE;
                                if(simbolosLenguaje.contains(palabraTransicion))
                                {
                                    indicePalabra=simbolosLenguaje.indexOf(palabraTransicion);
                                }
                                temporal.agregarTransicion(estadoDestino, indicePalabra,palabraTransicion);
                            }
                        }

                        this.estados.set(temporal.getNombre(),temporal);
                    }
                }
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
            System.out.println(e.getClass()+e.getMessage());
        }

    }

    public void escribirAutomataFinito()
    {
        boolean leyendoNombreArchivo = true;
        String fileName=null;
        try
        {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

            while(leyendoNombreArchivo)
            {
                System.out.println("Ingrese ruta de archivo .txt a escribir");
                fileName = br.readLine();
                if(fileName.endsWith(".txt"))
                    leyendoNombreArchivo = false;
            }

            FileWriter fw = new FileWriter(fileName);


            String estadosPorEscribir =estados.size()+"\n";
            fw.write(estadosPorEscribir);
            String simbolosPorEscribir="";
            for(int i = 0; i<simbolosLenguaje.size();i++)
            {
                simbolosPorEscribir+=simbolosLenguaje.get(i);
                if(i!=simbolosLenguaje.size()-1)
                    simbolosPorEscribir+=" ";
                else
                    simbolosPorEscribir+="\n";
            }
            fw.append(simbolosPorEscribir);

            int cantidadEstados = estados.size();

            for(int j = 0;j<cantidadEstados;j++)
            {
                Estado inicioTransicion = estados.get(j);
                String transicionesPorEscribir=inicioTransicion.getNombre()+" ";
              
                ArrayList<String> transicionesEstado = inicioTransicion.getTransiciones();
                ArrayList<Integer> destinoTransiciones = inicioTransicion.getDestinoTransicion();
                int cantidadSimbolos = transicionesEstado.size();
                transicionesPorEscribir+=transicionesEstado.get(0)+" "+destinoTransiciones.get(0);
                fw.append(transicionesPorEscribir);
                //Integer ultimo
                for(int i = 1;i< cantidadSimbolos;i++)
                {                    
                    
                    if(transicionesEstado.get(i-1).equals(transicionesEstado.get(i)))
                    {
                        if(transicionesEstado.get(0).equals(i))
                        {
                            transicionesPorEscribir=" "+destinoTransiciones.get(i);
                        }
                        else
                            transicionesPorEscribir+=transicionesEstado.get(i)+" "+destinoTransiciones.get(i);
                    }
                    // @todo hacer el salto por estados y transiciones tal y como es el formato de entrada
                    if(i==transicionesEstado.size())
                        transicionesPorEscribir+="\n";
                    fw.append(transicionesPorEscribir);
                }
            }
            fw.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
            System.out.println(e.getClass()+ e.getMessage());
        }
    }

    protected boolean  pertenecePalabraAlLenguaje(String palabra)
    {
        return pertenecePalabraAlLenguaje(palabra, simbolosLenguaje);
    }

    protected boolean  pertenecePalabraAlLenguaje(String palabra,ArrayList<String> palabrasgeneradas)
    {
        boolean pertenece = false;
        //@todo Revisar bien esto;
        int tamanoArreglo = palabrasgeneradas.size();
        int tamanoMinimo;
        if(palabrasgeneradas.contains(palabra))
            pertenece = true;
        else
        {
            ArrayList<String> palabraConcatenadas = new ArrayList<String>();
            for(int i = 0;i<tamanoArreglo;i++)
            {
                for(int j = 0;j<tamanoArreglo;j++)
                {
                    palabraConcatenadas.add(palabrasgeneradas.get(i)+palabrasgeneradas.get(j));
                }
            }
            tamanoMinimo = palabraConcatenadas.get(0).length();

            for(int j = 1;j<tamanoArreglo;j++)
            {
                int nuevoValor = palabraConcatenadas.get(j).length();
                if(tamanoMinimo>nuevoValor)
                    tamanoMinimo = nuevoValor;
            }

            if(palabra.length()>=tamanoMinimo)
                return pertenecePalabraAlLenguaje(palabra, palabraConcatenadas);
        }

        return pertenece;
    }

    protected Estado getEstadoPorNombre(Integer nombre)
    {
        Estado estado = null;
        for(int i = 0;i<estados.size();i++)
        {
            if(estados.get(i).getNombre().equals(nombre))
                estado = estados.get(i);
        }
        return estado;
    }

    /**
     * @return the esDeterminista
     */
    public boolean isEsDeterminista() {
        return esDeterminista;
    }

}
